package com.hbisedm.interninfosys.intern.websocket;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.hbisedm.interninfosys.config.GetHttpSessionConfigurator;
import com.hbisedm.interninfosys.intern.entity.ChatMsg;
import com.hbisedm.interninfosys.intern.entity.message.MessageVo;
import com.hbisedm.interninfosys.intern.entity.message.SampleMessage;
import com.hbisedm.interninfosys.intern.service.IChatMsgService;
import com.hbisedm.interninfosys.intern.service.IUserService;
import org.springframework.stereotype.Component;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

import javax.servlet.http.HttpSession;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArraySet;

@Component
@ServerEndpoint(value = "/websocket/{shopId}", configurator = GetHttpSessionConfigurator.class)
//此注解相当于设置访问URL
public class WebSocket {

    private HttpSession httpSession;
    private IUserService userService;
    private IChatMsgService chatMsgService;
    private Session session;
    private static CopyOnWriteArraySet<WebSocket> webSockets = new CopyOnWriteArraySet<>();
    private static Map<String, Session> sessionPool = new HashMap<String, Session>();

    @OnOpen
    public void onOpen(Session session, @PathParam(value = "shopId") String shopId, EndpointConfig config) {
        this.session = session;
        webSockets.add(this);
        sessionPool.put(shopId, session);
        System.out.println("【websocket消息】有新的连接，总数为:" + webSockets.size());
        this.httpSession = (HttpSession) config.getUserProperties().get(HttpSession.class.getName());
        System.out.println(httpSession == null);
        if(httpSession != null) {
            WebApplicationContext ctx = WebApplicationContextUtils.getRequiredWebApplicationContext(httpSession.getServletContext());
            chatMsgService = (IChatMsgService) ctx.getBean("chatMsgServiceImpl");
            userService = (IUserService) ctx.getBean("userServiceImpl");
        }
    }

    @OnClose
    public void onClose() {
        webSockets.remove(this);
        System.out.println("【websocket消息】连接断开，总数为:" + webSockets.size());
    }

    @OnMessage
    public void onMessage(String message) {
        //todo 转JSON 取出属性msg，name
        System.out.println("【websocket消息】收到客户端消息:" + message);
        if (!StrUtil.isEmpty(message)) {
            MessageVo messageVo = JSONObject.parseObject(message, MessageVo.class);
            System.out.println(messageVo);
            Integer fromId = messageVo.getFromId();
            Integer toId = messageVo.getToId();
            /**
             * 获取消息列表
             */
            if(messageVo.getType().equals("getMsg")) {
                List<SampleMessage> messageList = this.getMessageList(fromId, toId);
                for (SampleMessage sampleMessage : messageList) {
                    this.sendTextMessage(String.valueOf(fromId), JSON.toJSONString(sampleMessage));
                }
            }else {
                ChatMsg chatMsg = new ChatMsg();
                chatMsg.setMsgType(messageVo.getType());
                chatMsg.setSendContent(messageVo.getMsg());
                chatMsg.setSendUserId(messageVo.getFromId());
                chatMsg.setReceiveUserId(messageVo.getToId());
                System.out.println(chatMsg);
                boolean b = chatMsgService.saveOrUpdate(chatMsg);
                SampleMessage sampleMessage = new SampleMessage();
                sampleMessage.setMsg(chatMsg.getSendContent());
                sampleMessage.setName(userService.getById(chatMsg.getSendUserId()).getOthername());
                sampleMessage.setType(chatMsg.getMsgType());
                sampleMessage.setId(chatMsg.getSendUserId());
                sampleMessage.setTime(chatMsg.getUpdateTime());
                if (b) {
                    this.sendTextMessage(String.valueOf(messageVo.getFromId()), JSON.toJSONString(sampleMessage));
                    this.sendTextMessage(String.valueOf(messageVo.getToId()), JSON.toJSONString(sampleMessage));
                }
            }
        }
    }

    /**
     * 通过id获取对应的消息list
     * @param fromId
     * @param toId
     * @return
     */
    public List<SampleMessage> getMessageList(Integer fromId, Integer toId) {
        ArrayList<SampleMessage> sampleMessages = new ArrayList<>();
        SampleMessage sampleMessage;
        QueryWrapper<ChatMsg> chatMsgQueryWrapper = new QueryWrapper<>();
        chatMsgQueryWrapper
                .and(chatMsgQueryWrapper1 -> chatMsgQueryWrapper1.eq("SEND_USER_ID", fromId).or().eq("RECEIVE_USER_ID", fromId))
                .or()
                .and(chatMsgQueryWrapper1 -> chatMsgQueryWrapper1.eq("SEND_USER_ID", toId).or().eq("RECEIVE_USER_ID", toId));

        List<ChatMsg> list = chatMsgService.list(chatMsgQueryWrapper);

        for (ChatMsg chatMsg : list) {
            sampleMessage = new SampleMessage();
            sampleMessage.setMsg(chatMsg.getSendContent());
            sampleMessage.setName(userService.getById(chatMsg.getSendUserId()).getOthername());
            sampleMessage.setType(chatMsg.getMsgType());
            sampleMessage.setId(chatMsg.getSendUserId());
            sampleMessage.setTime(chatMsg.getUpdateTime());
            sampleMessages.add(sampleMessage);
        }
        return sampleMessages;
    }

    // 此为广播消息
    public void sendAllMessage(String message) {
        for (WebSocket webSocket : webSockets) {
            System.out.println("【websocket消息】广播消息:" + message);
            try {
                webSocket.session.getAsyncRemote().sendText(message);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    // 此为单点消息 (发送文本)
    public void sendTextMessage(String shopId, String message) {
        Session session = sessionPool.get(shopId);
        if (session != null) {
            try {
                session.getBasicRemote().sendText(message);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    // 此为单点消息 (发送对象)
    public void sendObjMessage(String shopId, Object message) {
        Session session = sessionPool.get(shopId);
        if (session != null) {
            try {
                session.getAsyncRemote().sendObject(message);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

}